# PhotographsScreen - This screen contains a list/grid of photographs
# Copyright (C) 2007 Lauri Taimila
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2007, Lauri Taimila"
__author__ = "Lauri Taimila <lauri@taimila.com>"

import os
import gtk
import pango
import clutter
import gobject

# Widgets
from frontend.gui.widgets.image_menu import ImageMenu
from frontend.gui.widgets.list_indicator import ListIndicator
from frontend.gui.widgets.image_menu_item import ImageMenuItem
from frontend.gui.widgets.loading_animation import LoadingAnimation

from frontend.user_event import UserEvent
from frontend.gui.screens.screen import Screen
from frontend.gui.transitions.transition import Transition

class PhotographsScreen(Screen):
    """
    PhotographsScreen
    
    This screen displays a grid of photographs as thumbnails. User can select
    any photograph from this grid.
    """
    
    def __init__(self, ui, frontend, data):
        """
        Initialize screen
        
        @param frontend: FrontendClient object
        @param theme: Theme object
        @param data: List [screen title string, List of Image objects]
        """
        self.group = clutter.Group()
        Screen.__init__(self, ui.STAGE_WIDTH, ui.STAGE_HEIGHT)
        
        self.ui = ui
        self.frontend = frontend
        self.theme = frontend.getTheme()
        self.images = data[1]
    
        # Screen Title (Displayed at the bottom left corner)
        screen_title = clutter.Label()
        screen_title.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.13)) + "px")
        screen_title.set_color(self.theme.getColor("screentitle"))
        screen_title.set_text(data[0])
        screen_title.set_name("screen_title")
        screen_title.set_position(self.ui.x(0), self.ui.y(0.87))
        screen_title.show()
        self.group.add(screen_title)
        
        # Image Title (over album list)
        self.image_title = clutter.Label()
        self.image_title.set_text(" ")
        self.image_title.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.04167)) + "px")
        self.image_title.set_color(self.theme.getColor("title"))
        self.image_title.set_line_wrap(False)
        self.image_title.set_ellipsize(pango.ELLIPSIZE_END)
        self.image_title.set_position(self.ui.x(0.0586), self.ui.y(0.7943))
        self.image_title.show()
        self.group.add(self.image_title)
        
        self.image_desc = clutter.Label()
        self.image_desc.set_text(" ")
        self.image_desc.set_font_name(self.theme.getFont() + " " + str(self.ui.y(0.04167)) + "px")
        self.image_desc.set_color(self.theme.getColor("subtitle"))
        self.image_desc.set_line_wrap(True)
        self.image_desc.set_ellipsize(pango.ELLIPSIZE_END)
        self.image_desc.set_position(self.ui.x(0.0586), self.ui.y(0.9115))
        self.image_desc.show()
        self.group.add(self.image_desc)
        
        # Display throbber animation while loading photographs
        self.throbber = LoadingAnimation(40, clutter.Color(255,255,255,255), clutter.Color(128,128,128,128))
        self.throbber.set_position(self.ui.x(0.9), self.ui.y(0.9))
        self.throbber.show()
        self.group.add(self.throbber)
        
        # List indicator
        self._create_list_indicator()
        
        # Create photomenu
        self.menu = ImageMenu(self.theme)
        self.menu.set_visible_column_count(6)
        self.menu.set_position(self.ui.x(0.0586), self.ui.y(0.1823))
        
        if self.frontend.get_configuration().show_effects():
            self.menu.set_animate(True)
        
        self.menu.show()
        self.group.add(self.menu)
        
        photos = self.images
        gobject.timeout_add(25, self._create_photo_menuitems, photos)
        
        self._update_image_info(0)
        
        self.group.show()
        ui.getStage().add(self.group)
    
    def _create_photo_menuitems(self, photographs):
        """
        This function is called as async callback. It is also recursive
        function. This allows us load menu items in the background without
        blocking the user interface.
        """
        # Check if we should stop recursive calls (menu is complete)
        if len(photographs) > 0:
            photo = photographs[0]
            texture = clutter.Texture()
            buffer = gtk.gdk.pixbuf_new_from_file(photo.get_thumbnail_url())
            texture.set_pixbuf(buffer)
            item = ImageMenuItem(self.ui.x(0.1464), self.ui.y(0.1953), texture)
            item.set_userdata(photo)
            self.menu.add_actor(item)
            # Recursive call, remove first artist from the list
            gobject.timeout_add(15, self._create_photo_menuitems, photographs[1:])
            return False
        else:
            if self.frontend.get_configuration().show_effects():
                self.timeline = clutter.Timeline(35, 26)
                self.alpha = clutter.Alpha(self.timeline, clutter.smoothstep_inc_func)
                self.behaviour = clutter.BehaviourOpacity(255, 0, self.alpha)
                self.behaviour.apply(self.throbber)
                self.timeline.connect('completed', self._remove_throbber, None)
                self.timeline.start()
            else:
                self.throbber.hide()
                self.group.remove(self.throbber)
                del self.throbber
            return False

    def _remove_throbber(self, timeline, actor):
        """
        Callback function for timeline that fades out photograph menu throbber.
        This is called when animation is finished and we are free to remove
        throbber from memory.
        @param timeline: clutter.Timeline object
        @param actor: clutter.Actor object
        """
        self.throbber.hide()
        self.group.remove(self.throbber)
        del self.throbber
    
    def _update_image_info(self, number):
        """
        Update image information box.
        @param number: Number of image. This is index of the self.__images
        """
        image = self.images[number]
        name = image.get_title()
        desc = image.get_description()
        self.image_title.set_text(name)
        self.image_desc.set_text(desc)
        self.image_title.set_size(self.ui.x(0.366), self.ui.y(0.04167))
        self.image_desc.set_size(self.ui.x(0.366), self.ui.y(0.0911))
        
    def _create_list_indicator(self):
        """
        Create list indicator for albums list.
        """
        self.li = ListIndicator(self.ui.x(0.1464), self.ui.y(0.04427), self.theme, ListIndicator.HORIZONTAL)
        self.li.set_position(self.ui.x(0.9297) - self.li.get_width(), self.ui.y(0.7943))
        self.li.set_delimiter(" | ")
        self.li.show()
        self.li.set_maximum(len(self.images))
        self.li.set_current(1)
        self.group.add(self.li)
    
    def get_group(self):
        """
        Get all actors of the screen.
        @return clutter.Group 
        """
        return self.group

    def get_type(self):
        """Return screen type."""
        return Screen.NORMAL
    
    def get_name(self):
        """Return screen name (human readble)"""
        return "PhotographsScreen"
    
    def handle_user_event(self, event):   
        """ 
        Handle screen specific user events
        @param event: UserEvent object
        """
        type = event.get_type()
        
        if type == UserEvent.NAVIGATE_LEFT:
            self.menu.move(ImageMenu.LEFT)
            self._update_image_info(self.menu.get_current_postition())
            self.li.set_current(self.menu.get_current_postition() + 1)
            
        elif type == UserEvent.NAVIGATE_RIGHT:
            self.menu.move(ImageMenu.RIGHT)
            self._update_image_info(self.menu.get_current_postition())
            self.li.set_current(self.menu.get_current_postition() + 1)
            
        elif type == UserEvent.NAVIGATE_UP:
            self.menu.move(ImageMenu.UP)
            self._update_image_info(self.menu.get_current_postition())
            self.li.set_current(self.menu.get_current_postition() + 1)
        
        elif type == UserEvent.NAVIGATE_DOWN:
            self.menu.move(ImageMenu.DOWN)
            self._update_image_info(self.menu.get_current_postition())
            self.li.set_current(self.menu.get_current_postition() + 1)
        
        elif type == UserEvent.NAVIGATE_SELECT:
            index = self.menu.get_current_postition()
            self.ui.changeScreen(self.ui.createScreen("photo", [index, self.images]), 
                                 Transition.FORWARD)